﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Security.Cryptography;
using System.Text;

namespace Simple.Tools.Security
/// <summary>
/// 版 本 钢易智企2.0 V 2.0.0 钢易智企2.0
/// Copyright (c) 2023 杭州钢易科技有限公司
/// 创建人：曾东明
/// 日 期：2024
/// 描 述：
/// </summary>
{
	public static class Security
	{
		/// <summary>
		/// 创建加密字符串
		/// </summary>
		/// <param name="str">待加密</param>
		/// <param name="hash">输出加密字符串</param>
		/// <param name="salt">输出密钥</param>
		public static void CreateHash(string str, out byte[] hash, out byte[] salt)
		{
			using var hmac = new System.Security.Cryptography.HMACSHA512();
			salt = hmac.Key;
			hash = hmac.ComputeHash(System.Text.Encoding.UTF8.GetBytes(str));
		}
		/// <summary>
		/// 验证数据是否正确
		/// </summary>
		/// <param name="str">待验证数据</param>
		/// <param name="hash">正确的数据</param>
		/// <param name="salt">密钥</param>
		/// <returns></returns>
		public static bool Verify(string str, byte[] hash, byte[] salt)
		{
			if (string.IsNullOrEmpty(str))
			{
				return false;
			}
			using (var hmac = new System.Security.Cryptography.HMACSHA512(salt))
			{
				var computedHash = hmac.ComputeHash(System.Text.Encoding.UTF8.GetBytes(str));
				for (int i = 0; i < computedHash.Length; i++)
				{
					if (computedHash[i] != hash[i]) return false;
				}
			}
			return true;
		}
		/// <summary>
		/// md5
		/// </summary>
		/// <param name="source"></param>
		/// <param name="length"></param>
		/// <returns></returns>
		public static string Encrypt(string source, int length = 32)//默认参数
		{
			if (string.IsNullOrEmpty(source)) return string.Empty;
			HashAlgorithm provider = CryptoConfig.CreateFromName("MD5") as HashAlgorithm;
			byte[] bytes = Encoding.UTF8.GetBytes(source);//这里需要区别编码的
			byte[] hashValue = provider.ComputeHash(bytes);
			StringBuilder sb = new StringBuilder();
			switch (length)
			{
				case 16://16位密文是32位密文的9到24位字符
					for (int i = 4; i < 12; i++)
					{
						sb.Append(hashValue[i].ToString("x2"));
					}
					break;
				case 32:
					for (int i = 0; i < 16; i++)
					{
						sb.Append(hashValue[i].ToString("x2"));
					}
					break;
				default:
					for (int i = 0; i < hashValue.Length; i++)
					{
						sb.Append(hashValue[i].ToString("x2"));
					}
					break;
			}
			return sb.ToString();
		}

		/// <summary>
		/// 获取文件的MD5摘要
		/// </summary>
		/// <param name="fileName"></param>
		/// <returns></returns>
		public static string AbstractFile(string fileName)
		{
			if (string.IsNullOrEmpty(fileName))
			{
				throw new ArgumentNullException($"this  fileName is null or empty！");
			}

			if (System.IO.File.Exists(fileName) == false)
			{
				throw new ArgumentNullException($"file does not exist!");
			}
			using (FileStream file = new FileStream(fileName, FileMode.Open))
			{
				return AbstractFile(file);
			}
		}
		/// <summary>
		/// 根据stream获取文件摘要
		/// </summary>
		/// <param name="stream"></param>
		/// <returns></returns>
		public static string AbstractFile(Stream stream)
		{
			MD5 md5 = new MD5CryptoServiceProvider();
			byte[] retVal = md5.ComputeHash(stream);

			StringBuilder sb = new StringBuilder();
			for (int i = 0; i < retVal.Length; i++)
			{
				sb.Append(retVal[i].ToString("x2"));
			}
			return sb.ToString();
		}


		private static readonly RandomNumberGenerator Rng = RandomNumberGenerator.Create();

		/// <summary>
		/// AES加密 
		/// </summary>
		/// <param name="password"></param>
		/// <param name="key"></param>
		/// <returns>返回一个saltpassword</returns>
		public static string AesEncrypt(string password, string key)
		{
			if (string.IsNullOrEmpty(password) || string.IsNullOrEmpty(key))
			{
				return string.Empty;
			}
			byte[] encrypted;
			using (Aes aesAlg = Aes.Create())
			{
				aesAlg.Key = Encoding.ASCII.GetBytes(Encrypt(key));
				aesAlg.IV = aesAlg.Key[..16];
				ICryptoTransform encryptor = aesAlg.CreateEncryptor();
				using MemoryStream msEncrypt = new MemoryStream();
				using CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write);
				using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
				{
					swEncrypt.Write(password);
				}
				encrypted = msEncrypt.ToArray();
			}
			return Convert.ToBase64String(encrypted);
		}

		/// <summary>
		/// 解密
		/// </summary>
		/// <param name="slatPassword"></param>
		/// <param name="key"></param>
		/// <param name="password"></param>
		/// <returns></returns>
		public static bool  AesDescrypt(string slatPassword, string key,string password)
		{
			if (string.IsNullOrWhiteSpace(slatPassword))
			{
				return false;
			}
			string plaintext = string.Empty;
			using (Aes aesAlg = Aes.Create())
			{
				try
				{
					aesAlg.Key = Encoding.ASCII.GetBytes(Encrypt(key));
					aesAlg.IV = aesAlg.Key[..16];
					ICryptoTransform decryptor = aesAlg.CreateDecryptor();
					using MemoryStream msDecrypt = new MemoryStream(Convert.FromBase64String(slatPassword));
					using CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read);
					using StreamReader srDecrypt = new StreamReader(csDecrypt);
					plaintext = srDecrypt.ReadToEnd();
				}
				catch (Exception ex)
				{

				}
			}
			return plaintext == password;

		}
	}
}
